package com.qilu.careprogram.excelConfig;

import com.alibaba.excel.metadata.Head;
import com.alibaba.excel.metadata.data.CellData;
import com.alibaba.excel.metadata.data.WriteCellData;
import com.alibaba.excel.write.handler.CellWriteHandler;
import com.alibaba.excel.write.metadata.holder.WriteSheetHolder;
import com.alibaba.excel.write.metadata.holder.WriteTableHolder;
import com.alibaba.excel.write.metadata.style.WriteCellStyle;
import com.alibaba.excel.write.metadata.style.WriteFont;
import com.alibaba.excel.write.style.AbstractCellStyleStrategy;
import lombok.extern.slf4j.Slf4j;
import org.apache.poi.ss.usermodel.*;
import org.apache.poi.ss.util.CellRangeAddress;

import java.util.List;

/**
 * @description: 自定义单元格合并处理
 * @author:
 * @date
 * @version
 */
@Slf4j
public class CustomCellWriteHandler implements CellWriteHandler {
    private int optLastColumnIdx;
    // 需要合并的列
    private int[] mergeColumns;
    // 合并条件
    private MergeCondition mc;
    // 数据起始行
    private int startIdx;


    /**
     * @param optLastColumnIdx 操作需要使用的最后一列，
     *                         主要用于将合并操作定位到这一列，避免一些使用的到数据还未被填充到excel中,导致无法正常判断。
     * @param startIdx         数据的起始行，从0开始计数
     * @param mergeColumns     需要合并的列
     * @param mc               合并条件
     */
    public CustomCellWriteHandler(int optLastColumnIdx, int startIdx, int[] mergeColumns, MergeCondition mc) {
        this.optLastColumnIdx = optLastColumnIdx;
        this.startIdx = startIdx;
        this.mergeColumns = mergeColumns;
        this.mc = mc;
    }

    @Override
    public void beforeCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Row row, Head head, Integer integer, Integer integer1, Boolean aBoolean) {

    }

    @Override
    public void afterCellCreate(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDataConverted(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, WriteCellData cellData, Cell cell, Head head, Integer integer, Boolean aBoolean) {

    }

    @Override
    public void afterCellDispose(WriteSheetHolder writeSheetHolder, WriteTableHolder writeTableHolder, List<WriteCellData<?>> list, Cell cell, Head head, Integer integer, Boolean aBoolean) {
        // 获取行号
        int rowIndex = cell.getRowIndex();
        // 获取列号
        int columnIndex = cell.getColumnIndex();
        // 行号 <= 数据所在的行,不做处理，直接返回，行号为数据行的第二行时才继续。 列号不等于需要使用的最后一列，直接返回
        if (rowIndex <= startIdx || optLastColumnIdx != columnIndex) return;
        // 获取处理结果
        boolean merged = mc.merged(cell.getSheet().getRow(rowIndex), cell.getSheet().getRow(rowIndex - 1));
        // 需要合并
        if (merged) {
            // 遍历需要合并的列
            for (int mergeColumn : mergeColumns) {
                // 标志位
                boolean isMerged = false;
                // 获取所有合并配置
                Sheet sheet = writeSheetHolder.getSheet();
                List<CellRangeAddress> mergeRegions = sheet.getMergedRegions();
                // 遍历合并配置
                for (int i = 0; i < mergeRegions.size(); i++) {
                    CellRangeAddress cellRangeAddr = mergeRegions.get(i);
                    // 上一行的单元格在配置中，移除这个配置，修改末尾行下标后重新加入一下。
                    if (cellRangeAddr.isInRange(rowIndex - 1, mergeColumn)) {
                        sheet.removeMergedRegion(i);
                        cellRangeAddr.setLastRow(rowIndex);
                        sheet.addMergedRegion(cellRangeAddr);
                        // 修改标志位，表示在已经存在的合并配置中存在当前需要合并的信息。
                        isMerged = true;
                        break;
                    }
                }
                // 新增合并单元
                if (!isMerged) {
                    CellRangeAddress cellRangeAddress = new CellRangeAddress(rowIndex - 1, rowIndex, mergeColumn,
                            mergeColumn);
                    sheet.addMergedRegion(cellRangeAddress);
                }
            }
        }
    }


}

